#pragma once

#include "Instruction.hpp"
#include "Value.hpp"
#include "ilist.hpp"

#include <list>
#include <set>
#include <string>



class Function;
class Instruction;
class Module;

class BasicBlock : public Value, public ilist<BasicBlock>::node {

  using InstIter = ilist<Instruction>::iterator;

  public:
    ~BasicBlock() = default;
    static BasicBlock *create(Module *m, const std::string &name,
                              Function *parent) {//创建一个基本块
        auto prefix = name.empty() ? "" : "label_";
        return new BasicBlock(m, prefix + name, parent);
    }

    /****************api about cfg****************/
    std::list<BasicBlock *> &get_pre_basic_blocks() { return pre_bbs_; }// 获取前驱基本块列表
    std::list<BasicBlock *> &get_succ_basic_blocks() { return succ_bbs_; }// 获取后继基本块列表
    // 前驱/后继基本块列表的维护
    void add_pre_basic_block(BasicBlock *bb) { pre_bbs_.push_back(bb); }
    void add_succ_basic_block(BasicBlock *bb) { succ_bbs_.push_back(bb); }
    void remove_pre_basic_block(BasicBlock *bb) { pre_bbs_.remove(bb); }
    void remove_succ_basic_block(BasicBlock *bb) { succ_bbs_.remove(bb); }

    // 检查基本块是否以终结指令（ret、br）结尾
    bool is_terminated() const;
    // 获取终结指令， only accept valid case use
    Instruction *get_terminator();

    /****************api about Instruction****************/
    void add_instruction(Instruction *instr);// 添加指令
    void add_instr_begin(Instruction *instr) // 在 instr_list_ 头部插入指令，并设置 instr 的 parent
    { 
      instr_list_.push_front(instr);
      instr->set_parent(this);}

    void insert_before(const InstIter &pos, Instruction *instr) 
    { 
      // Insert the new instruction before the position node
      instr_list_.insert_before(pos, instr);
    }

    // 获取某指令的前一条/后一条指令
    Instruction *get_prev_instr(Instruction *instr) { return instr_list_.get_prev(instr); }
    Instruction *get_next_instr(Instruction *instr) { return instr_list_.get_next(instr); }
    
    void erase_instr(Instruction *instr) { instr_list_.erase(instr); }// 删除指令
    void remove_instr(Instruction *instr) // 删除指令，并将 parent 置空
    { 
      instr_list_.remove(instr); 
      instr->set_parent_null();
    }
    void remove_last_instruction(); // 移除最后一条指令
    ilist<Instruction> &get_instructions() { return instr_list_; } //获取Instruction列表
    bool empty() const { return instr_list_.empty(); }
    int get_num_of_instr() const { return instr_list_.size(); } //获取指令数量

    /****************api about accessing parent****************/
    Function *get_parent() { return parent_; } // 获取BasicBlock所属Function
    Module *get_module(); //获取所属Module
    void erase_from_parent(); 

    virtual std::string print() override; 

  private:
    BasicBlock(const BasicBlock &) = delete; // 禁用拷贝构造，防止错误复制 BasicBlock
    explicit BasicBlock(Module *m, const std::string &name, Function *parent); // 构造函数 explicit，防止隐式转换

    std::list<BasicBlock *> pre_bbs_; // 前驱基本块列表
    std::list<BasicBlock *> succ_bbs_; // 后继基本块列表
    ilist<Instruction> instr_list_; // 指令列表
    Function *parent_; // 指向所属Function
};
